//
//  Event.swift
//  SwiftTools
//
//  Created by Samuel Richard Magny on 2015-09-09.
//  Copyright (c) 2015 Samuel Richard Magny. All rights reserved.
//

import Cocoa

public class Event<T> {

    public typealias EventHandler = T -> ()
    
    public init()
    {
        
    }
    
    public func raise(data: T) {
        for handler in self.eventHandlers
        {
            handler.invoke(data)
        }
    }
    
    public func addHandler<U: AnyObject>(target: U, handler: (U) -> EventHandler) -> Disposable {
        let wrapper = EventHandlerWrapper(target: target, handler: handler, event: self)
        eventHandlers.append(wrapper)
        
        return wrapper
    }
    

    
    private var eventHandlers = [Invocable]()
}


private class EventHandlerWrapper<T: AnyObject, U> : Invocable, Disposable {
    weak var target: T?
    let handler: T -> U -> ()
    let event: Event<U>
    
    init(target: T?, handler: T -> U -> (), event: Event<U>) {
        self.target = target
        self.handler = handler
        self.event = event;
    }
    
    func invoke(data: Any) -> () {
        if let t = target {
            handler(t)(data as! U)
        }
    }
    
    func dispose() {
        event.eventHandlers =
            event.eventHandlers.filter { $0 !== self }
    }
}

private protocol Invocable: class {
    func invoke(data: Any)
}

public protocol Disposable {
    func dispose()
}
